<?php
/*
 * @Author: CHINAKAIYUAN<sunkaiyuan@namenode.cn>
 * @Date: 2022-02-02 19:42:06
 * @LastEditTime: 2023-11-11 14:32:18
 * @LastEditors: 孙开源 && sunkaiyuan@namenode.cn
 * @Description: 
 */

namespace App\Repositories;


use App\Models\ProProcessesInspect;
use App\Models\ProProcessesWip;
use App\Models\ProProcessesWipBack;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\Facades\Image;

/**
 * Summary of ProProcessesWipRepository
 * @property ProProcessesWipBack $mode_back
 * @property ProProcessesInspectRepository $inspec
 * @author sunkaiyuan
 */
class ProProcessesWipRepository extends Repositories
    {
    public $relation_models = ['company', 'process', 'material', 'open_card'=>['processrename','process_route'], 'outfactory', 'location', 'pro_dept'];

    public function boot(ProProcessesWip $model, ProProcessesWipBack $mode_back, ProProcessesInspectRepository $inspec)
        {
        $this->model     = $model;
        $this->mode_back = $mode_back;
        $this->inspec    = $inspec;
        }
    //数量为0 删除WIP
    private function removeWipIfEmpty($wip_data)
        {
        if ($wip_data->faultle_quantity == 0) {
            $this->mode_back->create($wip_data->attributesToArray());
            $wip_data->delete();
            }
        }
    //恢复库存
    public function restoreWip($wip_id, $quantity)
        {
        $wip_data                   = is_numeric($wip_id) ? $this->getWip(['id' => $wip_id]) : $wip_id;
        $wip_data->faultle_quantity += $quantity;
        $wip_data->save();
        return $wip_data->refresh();
        }
    //扣除库存
    public function subWipStorage($wip_data, $quantity)
        {
        $wip_data = is_numeric($wip_data) ? $this->getWip(['id' => $wip_data]) : $wip_data->refresh();
        if ($wip_data->faultle_quantity < $quantity) {
            fail("过数失败！缸号:{$wip_data->dyelot} 数量不足{$quantity}");
            }
        $wip_data->faultle_quantity -= $quantity;
        $wip_data->save();
        $this->removeWipIfEmpty($wip_data);
        }
    //增加新的库存
    private function addWipStorage($wip_data, $process_id, $pro_dept_id, $factory_id, $location_id, $in_quantity, $out_quantity, $is_scrap, $direction_id, $remark = "")
        {
        $new_wip_data = null;
        //库存是否返工库存
        $storage_direction_id = 0;
        //库存的返工工序ID 是多少
        $storage_direction_process_id = 0;
        if ($direction_id == -1) {
            //返工过数，库存绝对是返工库存
            $storage_direction_id = -1;
            //如果返工库存是别的工序返工过来的，保留返工工序ID不变，否则返工工序是当前工序
            if ($wip_data->direction_process_id > 0) {
                $storage_direction_process_id = $wip_data->direction_process_id;
                }
            else
                $storage_direction_process_id = $wip_data->process_id;
            }
        else if ($direction_id == 1) {
            //正常过数的库存 不是是返工库存，或者是当前工序返工的，库存不是是返工库存。否则依然是返工库存
            if ($wip_data->direction_id != -1 || $wip_data->direction_process_id == $process_id) {
                $storage_direction_id         = 1;
                $storage_direction_process_id = 0;
                }
            else {
                $storage_direction_id         = -1;
                $storage_direction_process_id = $wip_data->direction_process_id;
                }
            }

        if ($in_quantity > 0) {
            $new_wip_data                   = $this->getWip([
                'dyelot'               => $wip_data->dyelot,
                'process_id'           => $process_id,
                'outfactory_id'        => $factory_id ?? 0,
                'location_id'          => $location_id,
                'is_scrap'             => $is_scrap,
                'batchno'              => $wip_data->batchno,
                'color_name'           => $wip_data->color_name,
                'pro_dept_id'          => $pro_dept_id,
                'open_card_id'         => $wip_data->open_card_id,
                'direction_process_id' => $storage_direction_process_id,
                'direction_id'         => $storage_direction_id
            ], [
                'outfactory_id'        => $factory_id ?? 0,
                'open_card_id'         => $wip_data->open_card_id,
                'dyelot'               => $wip_data->dyelot,
                'material_id'          => $wip_data->material_id,
                'feeding_ratio'        => $wip_data->feeding_ratio,
                'hank'                 => $in_quantity / $out_quantity * $wip_data->hank,
                'faultle_quantity'     => 0,
                'process_id'           => $process_id,
                'batchno'              => $wip_data->batchno,
                'color_name'           => $wip_data->color_name,
                'company_id'           => $wip_data->company_id,
                'location_id'          => $location_id,
                'is_scrap'             => $is_scrap,
                'pro_dept_id'          => $pro_dept_id,
                'direction_id'         => $storage_direction_id,
                'direction_process_id' => $storage_direction_process_id,
                'remark'               => $remark
            ]);
            $new_wip_data->faultle_quantity += $in_quantity;
            $new_wip_data->save();

            }
        return $new_wip_data;
        }
    //过数WIP  到$process_id 工序
    public function swipeWipToProcess($wip_data, $process_id, $in_quantity, $scrap_quantity, $out_quantity = null, $pro_dept_id = null, $factory_id = null, $location_id = 0, $direction_id = 1, $remark = "")
        {
        //出库数量
        $out_quantity = $out_quantity ?? ($in_quantity + $scrap_quantity);
        $this->subWipStorage($wip_data, $out_quantity); //扣数
        $wip1 = $this->addWipStorage($wip_data, $process_id, $pro_dept_id, $factory_id, $location_id, $in_quantity, $out_quantity, 0, $direction_id, $remark); //新增工序库存
        $wip2 = $this->addWipStorage($wip_data, $process_id, $pro_dept_id, $factory_id, $location_id, $scrap_quantity, $out_quantity, 1, $direction_id); //新增工序库存
        return [$wip1, $wip2];
        }
    //获取工艺线路
    public function getRoutesByWip($wip_data)
        {
        return $wip_data->open_card->main->process_route->details;
        }
    //根据Wip获取下一个工序
    public function getNextProcessByWip($wip_data, $direction_id = 1)
        {
        return $this->getNextProcessByRoute($this->getRoutesByWip($wip_data), $wip_data->open_card->route_process_id, $direction_id);
        }
    //根据路由获取下一个工序
    public function getNextProcessByRoute($routes, $route_process_id, $direction_id = 1)
        {
        // dd($routes->toArray());
        $route_detail = $routes->filter(fn($v) => $v->id == $route_process_id)->first();
        if ($route_detail) {
            //返工过数还是 正常过数
            $process       = $direction_id == 1 ? $route_detail->next_process : $route_detail->front_process;
            $route_process = $direction_id == 1 ? $route_detail->next_route : $route_detail->front_route;
            if ($process == null) {
                fail("过数失败！已经是" . ($direction_id == 1 ? "最后" : "第") . "一道工序");
                }
            return [$process, $route_process];

            }
        else {
            fail("过数失败！未找到过数工艺！");
            }
        }
    //创建检验入库单
    public function createInpsectIfEnd($new_wip_data, $process_pass_id)
        {
        $last_route_detail = $this->getRoutesByWip($new_wip_data);
        $route_detail      = $last_route_detail->filter(fn($v) => $v->id == $new_wip_data->open_card->route_process_id)->first();
        $last_route_detail = $route_detail->next_route;
        if ($route_detail->next_route->next_route_id == 0)
            return $this->createInspect($new_wip_data, $last_route_detail->process->type_id, $new_wip_data->location_id == 0 ? $last_route_detail->process->location_id : $new_wip_data->location_id, $process_pass_id);
        }

    //删除由过数记录创建的检验单，一般情况下，是删除过数记录时删除的
    public function removeInspectIfAudit($old_wip_storage)
        {
        $inspec_model = $this->inspec->whereWip_id($old_wip_storage->id)->first();
        if ($inspec_model instanceof ProProcessesInspect) {
            if ($inspec_model->status_id == 1) {
                if ($inspec_model->open_card->is_sample != "1")
                    fail("检验单已入库！");
                else {
                    $this->inspec->noStockIn($inspec_model);
                    auditSave($inspec_model, false);
                    }
                //删除钱 恢复WIP库存
                // $this->restoreWip($old_wip_storage, $inspec_model->faultle_quantity);
                // $this->inspec->noStockIn($inspec_model);
                }

            $old_wip_storage->open_card->faultle_quantity -= $old_wip_storage->faultle_quantity;
            $old_wip_storage->open_card->save();
            return $inspec_model->delete();
            }
        }

    private function createInspect($wip_model, $type_id, $location_id, $process_pass_id)
        {

        $inspec_model = $this->inspec->create([
            'wip_id'           => $wip_model->id,
            'open_card_id'     => $wip_model->open_card_id,
            'batchno'          => $wip_model->open_card->batchno,
            'custno'           => $wip_model->open_card->custno,
            'cust_order'       => $wip_model->open_card->cust_order,
            'order_id'         => $wip_model->open_card->order?->id,
            'unit_id'          => $wip_model->open_card->unit_id,
            'roll_quantity'    => $wip_model->open_card->roll_quantity ?? 0,
            'needEndInspect'   => $wip_model->open_card->needEndInspect,
            'process_route_id' => $wip_model->open_card->main->process_route_id,
            'process_id'       => $wip_model->process_id,
            'location_id'      => $location_id,
            'material_id'      => $wip_model->material_id,
            'dyelot'           => $wip_model->dyelot,
            'color_name'       => $wip_model->color_name,
            'company_id'       => $wip_model->company_id,
            'open_quantity'    => $wip_model->faultle_quantity,
            'process_pass_id'  => $process_pass_id,
        ]);
        if ($inspec_model->open_card->needEndInspect == "0") {
            $this->inspec->stockIn($inspec_model);
            auditSave($inspec_model);
            }

        return $inspec_model;
        }
    /**
     * 更新$where 获取 wip 库存，不存在，就在back中找，还不存在就根据$attrib 创建
     * @param mixed $where
     * @param mixed $attrib
     * @return mixed
     * @author sunkaiyuan
     */
    public function getWip($where, $attrib = null)
        {
        $SumData      = $this->model->where($where)->first();
        $SumData_back = null;
        //未找到汇总库存
        if (isEmpty($SumData)) {
            //备份库存中查找
            $SumData_back = $this->mode_back->where($where)->first();
            //备份中也没有，就创建
            if (isEmpty($SumData_back)) {
                if ($attrib) {
                    $SumData = $this->model->create($attrib);
                    }
                else {
                    fail("没有找到WIP库存!");
                    }
                }
            else {
                //备份中有，根据备份创建一个汇总，删除备份
                $SumData = $this->model->create($SumData_back->toArray());
                $SumData_back->delete();
                }
            }
        return $SumData;
        }
    }